package com.loeng.module.infra.service.file;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.loeng.framework.common.pojo.PageResult;
import com.loeng.framework.common.util.io.FileUtils;
import com.loeng.framework.common.util.object.BeanUtils;
import com.loeng.module.infra.controller.admin.file.vo.file.FilePageReqVO;
import com.loeng.module.infra.controller.admin.file.vo.file.FileSaveReqVO;
import com.loeng.module.infra.dal.dataobject.file.FileDO;
import com.loeng.module.infra.dal.mysql.file.FileMapper;
import com.loeng.module.infra.framework.file.core.client.FileClient;
import com.loeng.module.infra.framework.file.core.util.FileTypeUtils;
import lombok.SneakyThrows;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;

import static com.loeng.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.loeng.module.system.enums.ErrorCodeConstants.FILE_NOT_EXISTS;

/**
 * 文件 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class FileServiceImpl implements FileService {

    @Resource
    private FileMapper fileMapper;
    @Resource
    private FileConfigService fileConfigService;

    /**
     * 保存文件，并返回文件的访问路径
     *
     * @param name    文件名称
     * @param path    文件路径
     * @param content 文件内容
     * @return 文件路径
     */
    @Override
    @SneakyThrows
    public String createFile(String name, String path, byte[] content) {
        // 计算默认的path名
        String type = FileTypeUtils.getMineType(content, name);
        if (StrUtil.isEmpty(path)) {
            path = FileUtils.generatePath(content, name);
        }
        // 如果 name 为空，则使用 path 填充
        if (StrUtil.isEmpty(name)) {
            name = path;
        }

        // 上传到文件存储器
        FileClient client = fileConfigService.getMasterFileClient();
        Assert.notNull(client, "客户端(master) 不能为空");
        String url = client.upload(content, path, type);

        // 保存到数据库
        FileDO file = FileDO.builder()
                .configId(client.getId()) .name(name) .path(path)
                .url(url) .type(type) .size(content.length)
                .build();
        fileMapper.insert(file);
        return url;
    }

    @Override
    public Long createFile(FileSaveReqVO createReqVO) {
        // 插入
        FileDO file = BeanUtils.toBean(createReqVO, FileDO.class);
        fileMapper.insert(file);
        // 返回
        return file.getId();
    }

    @Override
    public void updateFile(FileSaveReqVO updateReqVO) {
        // 校验存在
        validateFileExists(updateReqVO.getId());
        // 更新
        FileDO updateObj = BeanUtils.toBean(updateReqVO, FileDO.class);
        fileMapper.updateById(updateObj);
    }

    @Override
    @SneakyThrows
    public void deleteFile(Long id) {
        // 校验存在
        FileDO file = validateFileExists(id);
        // 从文件存储器删除
        FileClient fileClient = fileConfigService.getFileClient(file.getConfigId());
        Assert.notNull(fileClient, "客户端({}) 不能为空", file.getConfigId());
        fileClient.delete(file.getPath());
        // 删除
        fileMapper.deleteById(id);
    }

    private FileDO validateFileExists(Long id) {
        FileDO fileDO = fileMapper.selectById(id);
        if (fileDO == null) {
            throw exception(FILE_NOT_EXISTS);
        }
        return fileDO;
    }

    @Override
    public FileDO getFile(Long id) {
        return fileMapper.selectById(id);
    }

    @Override
    public PageResult<FileDO> getFilePage(FilePageReqVO pageReqVO) {
        return fileMapper.selectPage(pageReqVO);
    }

}